package com.chai.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;

/**
 * 切面类
 * aop的使用
 * @Component交给spring继续管理
 * @Aspect表示使用注解开发aop与SpringConfig中@EnableAspectJAutoProxy进行配合使用
 * */
@Component
@Aspect
public class MyAdvice {
    /**
     * 定义切入点,需要定义一个私有的无返回值和参数的方法。
     * 功能：在连接点中选择需要增强的功能的位置
     * @Pointcut:选择需要增强功能的位置
     * 切入点表达式：execution(访问修饰符  返回值  包名.类/接口名.方法名(参数)异常名)
     * 访问修饰符和异常名可以进行省略
     * */
    @Pointcut("execution(void com.chai.service.Impl.UserServiceImpl.save())")
    private void pt(){};
    /**
     * 前置通知
     * 进行增强的部分，下载方法中。即：通知
     * 需要继续指定增在所相对的位置，Before是在切入点之前执行
     * */
    @Before("pt()")
    public void enhance(JoinPoint joinPoint){
        //获取参数
        Object[] args = joinPoint.getArgs();
        System.out.println(args.toString());
        System.out.println("在这里进行方法的增强");
    }
    /**
     * 后置通知
     *
     * */
    @After("pt()")
    public void after(){
        System.out.println("后置通知执行");
    }
    /**
     * 环绕通知
     * 定义ProceedingJoinPoint对于原始方法的调用
     * */
    @Around("pt()")
    public Object around(@NotNull ProceedingJoinPoint pjp) throws Throwable {
        Signature signature = pjp.getSignature();
        System.out.println("类名(className)："+signature.getDeclaringType());
        System.out.println("方法名称(methodName)："+signature.getName());
        //获取参数
        Object[] args = pjp.getArgs();
        System.out.println("环绕通知的前面");
        //对于原方法的调用
        Object proceed = pjp.proceed();
        System.out.println("环绕通知的后面");
        return proceed;
    }
    /**
     * 返回后通知
     * */
    @AfterReturning("pt()")
    public void afterReturning(){
        System.out.println("返回后通知");
    }
    /**
     * 发生异常后通知
     * */
    @AfterThrowing("pt()")
    public void afterThrowing(){
        System.out.println("抛出异常后通知");
    }
}
